<?php

/**
 *    支付宝支付方式插件
 *
 *    @author    andery
 */

class AlipayPayment 
{
    /* 支付宝网关 */
    private $_gateway   =   'https://www.alipay.com/cooperate/gateway.do?';
    private $_code      =   'alipay';
    private $_config    = array();
    
    public function __construct($payment_config)
    {
        $this->_config = $payment_config;
    }
    
    /**
     * 获取支付链接
     * 
     * @author andery
     * @param array $order_info  待支付的订单信息
     * @return string
     */
    public function create_url($order_info)
    {
        // 构造要请求的参数数组
        $parameter = array(
            // 基本参数
            'service'           => $this->_config['alipay_service'], //接口名称
            'partner'           => $this->_config['alipay_partner'], //合作身份者ID
            'return_url'        => $this->_config['return_url'], //交易过程中服务器通知的页面 
            'notify_url'        => $this->_config['notify_url'], //付完款后跳转的页面
            '_input_charset'    => 'utf-8', //字符编码格式 目前支持 GBK 或 utf-8
            
            // 业务参数
            'out_trade_no'      => $order_info['orderid'], //外部交易号
            'subject'           => $order_info['subject'], //商品名称
            'body'              => $order_info['body'], //商品描述
            'price'             => $order_info['total'], //应付总价
            'quantity'          => $order_info['items'], //商品个数
            'payment_type'      => '1', //支付类型
            
            'logistics_type'    => 'EXPRESS', //物流类型
            'logistics_fee'     => $order_info['shipping_fee'], //物流费用
            'logistics_payment' => 'SELLER_PAY', //物流支付类型
            
            'seller_email'=> $this->_config['seller_email'], //签约支付宝账号或卖家支付宝帐户
        );
        
        $url = $this->_gateway;
        $sign_type = $this->_config['sign_type'];
        $parameter = $this->_para_filter($parameter);
        $parameter = $this->_arg_sort($parameter);
        
        $arg = $this->_create_linkstring_urlencode($parameter);
        $sign = $this->_get_sign($parameter, $sign_type);
        
		//把网关地址、已经拼接好的参数数组字符串、签名结果、签名类型，拼接成最终完整请求url
        $url .= $arg . "&sign=" . $sign . "&sign_type=" . $sign_type;
        return $url;
    }
    
    /**
     * 支付宝主动通知
     */
    public function verify_notify($order_info)
    {
        $notify = $_POST;
        $check_result = $this->_check_notify($notify);
        if ($check_result) {
            //通知验证成功，开始本地订单信息验证
            if ($order_info['order_id'] != $notify['out_trade_no']) {
                //订单号不对
                return false;
            }
            if ($order_info['order_amount'] != $notify['price']) {
                //订单金额不对
                return false;
            }
            // 根据返回结果处理
            switch ($notify['trade_status']) {
                // 买家已在支付宝交易管理中产生了交易记录且付款成功，但卖家没有发货
                case 'WAIT_SELLER_SEND_GOODS':
                    $order_status = OS_ACCEPTED;
                    break;
                // 卖家已经发了货，但买家还没有做确认收货的操作
                case 'WAIT_BUYER_CONFIRM_GOODS':
                    $order_status = OS_SHIPPED;
                    break;
                // 买家已经确认收货，这笔交易完成
                case 'TRADE_FINISHED':
                    $order_status = ORDER_FINISHED;
                    break;
            }
            switch ($notify['refund_status']) {
                // 退款成功，取消订单
                case 'REFUND_SUCCESS':
                    $order_status = OS_CANCELED;
                    break;
            }
            return $order_status;
        } else {
            return false;
        }
    }
    
    public function _check_notify($notify)
    {
        Someze::import('CRequest');
        $veryfy_url = $this->_gateway. "service=notify_verify&partner=" . $this->_config['alipay_partner'] . "&notify_id=" . $notify["notify_id"];
        $verify_result = CRequest::socket_request($veryfy_url);
        //生成签名结果
        if(empty($_POST)) {
            return false;
        } else {
            $fileter_notify = _para_filter($notify);
            $local_sign = $this->_get_sign($fileter_notify, $this->_config['sign_type']);
			return ($local_sign == $notify["sign"]);
        }
    }
    
    /**
     * 加密字符串
     * @param string $prestr 需要加密的字符串
     * @return string $sign 加密之后的字符串
     */
    private function _get_sign($parameter, $sign_type)
    {
        $sign='';
        $prestr = $this->_create_linkstring($parameter);
        $prestr .= $this->_config['security_code'];

        $sign_type = strtoupper($sign_type);
        if ($sign_type == 'MD5') {
            $sign = md5($prestr);
        } elseif ($sign_type =='DSA') {
            //DSA 签名方法待后续开发
            die("DSA 签名方法待后续开发，请先使用MD5签名方式");
        } else {
            die("支付宝暂不支持".$sign_type."类型的签名方式");
        }
        return $sign;
    }
    
    /**除去数组中的空值和签名参数
     *@param array $parameter 加密参数组
     *@return 去掉空值与签名参数后的新加密参数组
     */
    private function _para_filter($parameter) 
    {
        $para = array();
        foreach ($parameter as $key=>$val) {
            if ($key == "sign" || $key == "sign_type" || $val == "") {
                continue;
            } else {
                $para[$key] = $parameter[$key];
            }
        }
        return $para;
    }
    
    /**
     * 对数组排序
     * @param array $array 排序前的数组
     * @return array $array 排序后的数组
     */
    private function _arg_sort($array)
    {
        ksort($array);
        reset($array);
        return $array;
    }
    
    /**
     * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
     * @param array $array 需要拼接的数组
     * @return string $arg 拼接完成以后的字符串
     */
    private function _create_linkstring($array)
    {
        $arg  = "";
        foreach ($array as $key=>$val) {
            $arg .= "$key=" .$val. "&";
        }
        $arg = substr($arg, 0, -1);
        return $arg;
    }
    
    /**
     * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
     * 使用场景：GET方式请求时，对URL的中文进行编码
     * @param array $array 需要拼接的数组
     * @return string $arg 拼接完成以后的字符串
     */
    private function _create_linkstring_urlencode($array)
    {
        $arg  = "";
        foreach ($array as $key=>$val) {
            if ($key != "service" && $key != "_input_charset") {
                $arg.=$key."=".urlencode($val)."&";
            } else {
                $arg.=$key."=".$val."&";
            }
        }
        $arg = substr($arg, 0, -1);
        return $arg;
    }
}